home *** CD-ROM | disk | FTP | other *** search
- /*
- File: FileLogging.c
-
- Contains: File logging engine for OTStreamLogViewer.
-
- Written by: Quinn "The Eskimo!"
-
- Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- */
-
- #define qDebug 1
-
- /////////////////////////////////////////////////////////////////////
- // Standard C stuff.
-
- #import <stdio.h>
-
- /////////////////////////////////////////////////////////////////////
- // Pick up standard OT APIs.
-
- #import <OpenTransport.h>
-
- /////////////////////////////////////////////////////////////////////
- // Pick up the low-level OT APIs.
-
- #import <OTDebug.h>
-
- /////////////////////////////////////////////////////////////////////
- // Pick up toolbox stuff.
-
- #import <TextUtils.h>
- #import <Errors.h>
-
- /////////////////////////////////////////////////////////////////////
- // Pick up our resource definitions.
-
- #import "StreamLogResources.h"
-
- /////////////////////////////////////////////////////////////////////
- // Pick up our own prototypes.
-
- #import "FileLogging.h"
-
- /////////////////////////////////////////////////////////////////////
- // OTDebugStr is not defined in any OT header files, but it is
- // exported by the libraries, so we define the prototype here.
-
- extern pascal void OTDebugStr(const char* str);
-
- /////////////////////////////////////////////////////////////////////
-
- static OSStatus FSWriteQAtLEOF(SInt16 fileRefNum, SInt32 count, void *buffer)
- // Writes the count bytes at buffer to the end of fileRefNum.
- {
- ParamBlockRec pb;
-
- pb.ioParam.ioRefNum = fileRefNum;
- pb.ioParam.ioBuffer = buffer;
- pb.ioParam.ioReqCount = count;
- pb.ioParam.ioPosMode = fsFromLEOF;
- pb.ioParam.ioPosOffset = 0;
-
- return PBWriteSync(&pb);
- }
-
- /////////////////////////////////////////////////////////////////////
- // File Logging Stuff
-
- static SInt16 gLogFileRefNum = 0;
- // The file refnum of the log file, or 0 if logging
- // is not active.
-
- static char gLogAssemblyBuffer[10240];
- // A temporary buffer used to assemble log text
- // we're about to write to the file.
-
- static UInt32 gTicksOfLastFileWrite;
- // The TickCount time at which we last wrote to the file.
- // If TickCount is more than this value plus
- // kTicksPerFlush, we need to flush the file now.
-
- enum {
- kTicksPerFlush = 6,
- // Number of ticks from when we write to a file to when
- // we perform a FlushFile to make sure it gets to the disk.
-
- kLogFileCleanTicks = (UInt32) -(kTicksPerFlush+1)
- // When the file is flushed we set gTicksOfLastFileWrite
- // to this value to prevent further writes from happening.
- // This corresponds to "far in the future".
- };
-
- static char kStartFileLogString[] = "Sequence\tFlags\tFlags (as number)\tTime (ms)\tReal Time\tModule ID\tStream ID\tMessage\r";
- // When we start logging, we write this line to the file
- // to give the user some idea of the what each column means.
-
- extern OSStatus StartFileLogging(void)
- // See comment in interface part.
- {
- OSStatus err;
- Str255 logFileName;
- FSSpec logFile;
-
- OTAssert("StartFileLogging: We're already logging!", gLogFileRefNum == 0);
-
- gTicksOfLastFileWrite = kLogFileCleanTicks;
-
- // Open up the log file, creating it if necessary.
-
- GetIndString(logFileName, rMiscStrings, strLogFileName);
- err = FSMakeFSSpec(-1, fsRtDirID, logFileName, &logFile);
- if (err == fnfErr) {
- err = noErr;
- }
- if (err == noErr) {
- (void) FSpCreate(&logFile, 'R*ch', 'TEXT', 0);
- err = FSpOpenDF(&logFile, fsWrPerm, &gLogFileRefNum);
- if (err != noErr) {
- gLogFileRefNum = 0;
- }
- }
-
- // Write the header to the file.
-
- if (err == noErr) {
- err = FSWriteQAtLEOF(gLogFileRefNum, OTStrLength(kStartFileLogString), kStartFileLogString);
- }
-
- // Clean up.
-
- if (err != noErr) {
- if ( gLogFileRefNum != 0 ) {
- StopFileLogging();
- }
- }
-
- return err;
- }
-
- enum {
- kFlagsToStringBufferSize = 50
- // flagStr must point to a buffer of at least 50 characters.
- };
-
- static void FlagsToString(char flags, char *flagStr)
- // Create a verbose string that represents the various
- // flag bits in flags.
- {
- flagStr[0] = 0;
-
- if ((flags & SL_TRACE) != 0) {
- OTStrCat(flagStr, "Trace ");
- }
- if ((flags & SL_ERROR) != 0) {
- OTStrCat(flagStr, "Error ");
- }
- if ((flags & SL_CONSOLE) != 0) {
- OTStrCat(flagStr, "Console ");
- }
-
- if ((flags & SL_FATAL) != 0) {
- OTStrCat(flagStr, "Fatal ");
- }
- if ((flags & SL_NOTIFY) != 0) {
- OTStrCat(flagStr, "Notify ");
- }
- if ((flags & SL_WARN) != 0) {
- OTStrCat(flagStr, "Warning ");
- }
- if ((flags & SL_NOTE) != 0) {
- OTStrCat(flagStr, "Notice ");
- }
-
- // Remove the trailing space.
-
- if ( flagStr[0] != 0 ) {
- flagStr[ OTStrLength(flagStr) - 1 ] = 0;
- }
- }
-
- extern char *LogEntryToCString(LogEntryPtr thisEntry)
- // See comment in interface part.
- {
- Str255 dateStr;
- Str255 timeStr;
- char flagStr[kFlagsToStringBufferSize];
-
- OTAssert("LogEntryToCString: paramErr", thisEntry != nil);
-
- FlagsToString(thisEntry->fLogHeader.flags, flagStr);
-
- // ltime is generated by calling OTGetTimeStamp and converting
- // the result to milliseconds using OTTimeStampInMilliseconds.
-
- // ttime is the result of the low-memory global Time, which
- // is the same as the result of GetDateTime.
-
- DateString(thisEntry->fLogHeader.ttime, shortDate, dateStr, nil);
- TimeString(thisEntry->fLogHeader.ttime, true, timeStr, nil);
-
- sprintf(gLogAssemblyBuffer, "%ld\t%s\t0x%02x\t0x%08x\t%#s %#s\t%d\t%d\t%s\r",
- thisEntry->fLogHeader.seq_no,
- flagStr,
- thisEntry->fLogHeader.flags,
- thisEntry->fLogHeader.ltime,
- dateStr,
- timeStr,
- thisEntry->fLogHeader.mid,
- thisEntry->fLogHeader.sid,
- (char *) thisEntry + sizeof(LogEntry)
- );
- return gLogAssemblyBuffer;
- }
-
- extern void RecordLogEntryToFile(LogEntryPtr thisEntry)
- // See comment in interface part.
- {
- OSStatus junk;
-
- if ( gLogFileRefNum != 0 ) {
-
- (void) LogEntryToCString(thisEntry);
-
- junk = FSWriteQAtLEOF(gLogFileRefNum, OTStrLength(gLogAssemblyBuffer), gLogAssemblyBuffer);
- OTAssert("RecordLogEntryToFile: Error writing log entry", junk == noErr);
-
- gTicksOfLastFileWrite = TickCount();
- }
- }
-
- extern void FileLoggingIdle(void)
- // See comment in interface part.
- {
- OSStatus junk;
- ParamBlockRec pb;
-
- if ( gLogFileRefNum != 0 ) {
- if ( TickCount() > gTicksOfLastFileWrite + kTicksPerFlush ) {
- pb.ioParam.ioRefNum = gLogFileRefNum;
- junk = PBFlushFileSync(&pb);
- OTAssert("DoIdle: FlushFile returned an error", junk == noErr);
- gTicksOfLastFileWrite = kLogFileCleanTicks;
- }
- }
- }
-
- extern Boolean FileLoggingActive(void)
- // See comment in interface part.
- {
- return gLogFileRefNum != 0;
- }
-
- extern void StopFileLogging(void)
- // See comment in interface part.
- {
- OSStatus junk;
-
- OTAssert("StopFileLogging: We're not logging!", gLogFileRefNum != 0);
-
- junk = FSClose(gLogFileRefNum);
- OTAssert("StopFileLogging: Could not close log file", junk == noErr);
- gLogFileRefNum = 0;
- }
-